﻿using System.Threading.Tasks;
using System.Timers;

namespace SuiHan.Commons.Daemon {
    /// <summary>
    /// 守护进程配置
    /// </summary>
    public abstract class DaemonProcess {
        private Timer timer;
        private bool pending;

        /// <summary>
        /// 任务执行间隔(ms)
        /// </summary>
        public double Interval { get; set; } = 3000;

        /// <summary>
        /// 排序
        /// </summary>
        public int Order { get; set; }

        /// <summary>
        /// 是否在程序退出时杀死进程
        /// </summary>
        public bool Killable { get; set; }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
            Handle();
        }

        /// <summary>
        /// 开始监视进程
        /// </summary>
        public virtual void Start() {
            Handle();
            Task.Factory.StartNew(() => {
                if (timer == null) {
                    timer = new Timer(Interval);
                    timer.Elapsed += Timer_Elapsed;
                }

                timer.Start();
            });
        }

        /// <summary>
        /// 停止守护进程
        /// </summary>
        public void Stop() {
            timer?.Stop();
        }

        private void Handle() {
            if (pending) return;

            BeforeRun();
            if (IsRunning()) {
                return;
            }

            pending = true;
            RunProcess();
            pending = false;
        }

        /// <summary>
        /// 在任务执行之前调用的方法
        /// </summary>
        protected virtual void BeforeRun() {
        }

        /// <summary>
        /// 返回进程是否在运行中
        /// </summary>
        protected abstract bool IsRunning();

        /// <summary>
        /// 启动进程
        /// </summary>
        protected abstract void RunProcess();

        /// <summary>
        /// 杀死进程
        /// </summary>
        public virtual void KillProcess() {
        }
    }
}
